#include "client.h"

chat_client::chat_client(boost::asio::io_service& io_service,
        tcp::resolver::iterator endpoint_iterator): 
        io_service_(io_service), socket_(io_service) {
            do_connect(endpoint_iterator);
    }

void chat_client::write(const chat_message& msg)
 {
            // write是由主线程往子线程写东西
            // 所以需要使用post提交到子线程运行
            // 使得所有io操作都由io_service的子线程掌握
    io_service_.post(
            [this, msg] () {

                bool write_in_progress = !write_msgs_.empty();
                write_msgs_.push_back(msg);
                if(!write_in_progress) {
                    do_write();
                }
            }
            );
}

void chat_client::close(){
    io_service_.post(
            [this] () {
                socket_.close();
            }
            );
}

void chat_client::do_connect(tcp::resolver::iterator endpoint_iterator){
    boost::asio::async_connect(
            socket_,
                endpoint_iterator,
                [this] (boost::system::error_code ec, tcp::resolver::iterator it) {
                    if(!ec) {
                        // 如果连接成功，读取消息头
                        do_read_header();
                    }
                }
            );  
}

void chat_client::do_read_header(){
    boost::asio::async_read(
            socket_,
            boost::asio::buffer(read_msg_.data(), chat_message::header_length),
            [this] (boost::system::error_code ec, std::size_t length) {
                if(!ec && read_msg_.decode_header()) {
                    // 如果没有错误，并且Decode_header成功，成功读取到body_length
                    do_read_body();
                }else {
                    // 读取失败时关闭与服务端的连接，退出事件循环
                    socket_.close();
                }
            }
        );
}

void chat_client::do_read_body() {
    boost::asio::async_read(
        socket_,
        boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
            [this] (boost::system::error_code ec, std::size_t length) {
            if(!ec) {
                std::cout.write(read_msg_.body(), read_msg_.body_length());
                std::cout << "\n";
                    // 调用do_read_header函数串联起事件链，接着读
                    do_read_header();
                    }else {
                    socket_.close();
                }
                            
            }
        );
}


void chat_client::do_write() {
    boost::asio::async_write(
                socket_,
                boost::asio::buffer(
                    write_msgs_.front().data(),
                    write_msgs_.front().length()
                    ),
                [this] (boost::system::error_code ec, std::size_t length) {
                    if(!ec) {
                        // 一直写直到写完
                        write_msgs_.pop_front();
                        if(!write_msgs_.empty()) {
                            do_write();
                        }
                    }else {
                        socket_.close();
                    }
                }
            );
}